/*
 * Copyright (C) 2011 Olivier Pothin and contributors
 *
 * GNU General Public License v2.0
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/** 
 * 
 * @author Olivier Pothin
 * @description Display a single word with chinese, french and pinyin equivalence
 *
 */
package opot.activities;

import java.util.Random;

import com.google.android.apps.analytics.GoogleAnalyticsTracker;

import opot.db.WordProvider;
import opot.dto.Question;
import opot.dto.Word;
import opot.exceptions.WordNotFoundException;
import opot.utils.QuizzController;
import opot.utils.WordRandomizer;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Rect;
import android.net.MailTo;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.GestureDetector;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Animation.AnimationListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class WordDisplayer extends Activity implements OnClickListener, AnimationListener {

	public static final String DisplayedWordIdKey = "_WordDisplayer";
	public static final int REQUEST_PREFERENCE = 100;

	private int currentWordId = 0;
	private int currentRealTranslationDisplayID;
	private int lastWordId;
	private final static int minVelocity = 100;

	private static final int[] translationsDisplayID = {R.id.translationDisplay_first,R.id.translationDisplay_second,R.id.translationDisplay_third,R.id.translationDisplay_fourth};

	private String french = "";
	private String chinese = "";
	private String pinyin = "";

	public static final int MODE_NORMAL = 1;
	public static final int MODE_RANDOM = 2;
	public static int NB_RANDOM = 20;

	// In this case the wanted word is in chinese
	public static final int MAIN_LANGUAGE_CH = 3;
	// Case where wanted word is in french
	public static final int MAIN_LANGUAGE_FR = 4;

	private int mode;
	private int mainLanguage;

	private View animatedAnwser;

	/** Gesture detector pour la gestion des mouvement au sein du layout contenant les mots **/
	private GestureDetector mGestureDetector;

	/** {@link Activity} Method **/
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);		
		setContentView(R.layout.worddisplayer);
		mode = MODE_NORMAL;
		mainLanguage = MAIN_LANGUAGE_CH;

		findViewById(R.id.bouton_droite_id).setOnClickListener(this);
		findViewById(R.id.menubouton).setOnClickListener(this);
		findViewById(R.id.bouton_dico_courant).setOnClickListener(this);
		findViewById(R.id.mainDisplay).setOnClickListener(this);

		registerForContextMenu(findViewById(R.id.menubouton));
		registerTranslations();

		if(getIntent().getExtras() != null)
			currentWordId = getIntent().getExtras().getInt(DisplayedWordIdKey);

		Uri allWords = Word.Words.CONTENT_URI;
		Log.d("WORD","URI : "+allWords);
		
		Cursor c = managedQuery(allWords, null, null, null, "created desc");
		lastWordId = c.getCount();
		c.close();
		currentWordId = (currentWordId != 0) ? currentWordId : 1;
		loadAndDisplayWordFromId(currentWordId);
		mGestureDetector = new GestureDetector(this,mScrollHandler,null);
		// GoogleAnalyticsTracker.getInstance().start("UA-23537172-1", this);
		// GoogleAnalyticsTracker.getInstance().trackPageView("/VueQuizz");
	}


	/**
	 * Register each of the 4 text view used to display clickable word suggestion 
	 * during a quizz with a {@link TranslationListener} 
	 */
	private void registerTranslations() {

		for (int trans : translationsDisplayID){
			findViewById(trans).setOnClickListener(translationListener);
		}

	}
	
	/**
	 * {@link Activity} Method
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		loadPreferences();
		if(requestCode == REQUEST_PREFERENCE && mode == MODE_RANDOM) {
			//ON reset le quizz avec les nouvelles préférences
			changeMode(MODE_RANDOM);
		}
	}

	/**
	 * {@link Activity} Method
	 */
	@Override
	protected void onResume() {
		super.onResume();
		//displayCurrentMode();
		loadPreferences();
	}

	/**
	 * Set the {@link TextView} displaying the current word with its value
	 * does not impact false translation.
	 * Also set the {@link currentRealTranslationDisplayID} attribute
	 */
	protected void displayCurrentWord() {

		try {
			Random rd = new Random();
			currentRealTranslationDisplayID = translationsDisplayID[rd.nextInt(4)];
			fillDummy();

			Button btn;
			TextView v;

			switch(mainLanguage) {

			case MAIN_LANGUAGE_CH:
				if(!french.equals("")) {
					btn = (Button)findViewById(currentRealTranslationDisplayID);
					btn.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
					btn.setTextSize(TypedValue.COMPLEX_UNIT_SP, Integer.parseInt(getString(R.string.french_translation_display_size)));
					btn.setText(french);
				}
				if(!chinese.equals("")) {
					v = (TextView)findViewById(R.id.mainDisplay);
					v.setTextSize(TypedValue.COMPLEX_UNIT_SP, Integer.parseInt(getString(R.string.chinese_main_display_size)));
					//v.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
					v.setText(chinese);
					v = (TextView)findViewById(R.id.textBackground);
					v.setText(chinese);
				}
				if(!pinyin.equals("")) {
					v = (TextView)findViewById(R.id.pinyinDisplay);
					v.setText(pinyin);
				}break;
			case MAIN_LANGUAGE_FR:

				if(!french.equals("")) {

					v = (TextView)findViewById(R.id.mainDisplay);
					v.setTextSize(TypedValue.COMPLEX_UNIT_SP, Integer.parseInt(getString(R.string.french_main_display_size)));
					v.setText(french);
				}
				if(!chinese.equals("")) {

					btn = (Button)findViewById(currentRealTranslationDisplayID);
					btn.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
					btn.setTextSize(TypedValue.COMPLEX_UNIT_SP, Integer.parseInt(getString(R.string.chinese_translation_display_size)));
					btn.setText(chinese);
				}

				v = (TextView)findViewById(R.id.pinyinDisplay);
				v.setText("");
				v = (TextView)findViewById(R.id.textBackground);
				v.setText("");
				break;
			}
		}catch (WordNotFoundException e) {
			//TODO Gestion exception
		}
	}

	/**
	 *  Load word from database using id provided by intent
	 *  @param wordID the row in database
	 */
	protected void loadAndDisplayWordFromId(int wordID) {

		Uri word = Uri.parse(
				"content://"+WordProvider.AUTHORITY+"/words/"+wordID);

		Cursor c = managedQuery(word, null, null, null, "created desc");

		if (c.moveToFirst()) {

			french = c.getString(c.getColumnIndex(Word.Words.COLUMN_NAME_FRENCH));
			chinese = c.getString(c.getColumnIndex(Word.Words.COLUMN_NAME_CHINESE));
			pinyin = c.getString(c.getColumnIndex(Word.Words.COLUMN_NAME_PINYIN));
			c.close();
			displayCurrentWord();
		}

	}

	/**
	 * Callback of the {@link OnClickListener}
	 */
	public void onClick(View v) {

		switch (v.getId()) {

		case R.id.menubouton:
			openContextMenu(v);
			break;

		case R.id.bouton_droite_id:
			actionBoutonDroite();
			break;

		case R.id.bouton_dico_courant:
			Intent intent = new Intent(this,Dictionary.class);
			intent.putExtra(Dictionary.DICTIONARY_INITIAL_SELECTED, currentWordId);
			startActivity(intent);
			break;


		case R.id.mainDisplay:
			switch(mainLanguage){
			case MAIN_LANGUAGE_CH:
				View t = findViewById(R.id.pinyinDisplay);
				if (t.getVisibility() == View.VISIBLE) {
					t.setVisibility(View.INVISIBLE);
				}else {
					t.setVisibility(View.VISIBLE);
				}
				break;
			}
			break;
		}
	}
	
	/**
	 * In {@link MODE_NORMAL} display the next word from database
	 * In {@link MODE_RANDOM} display a random new word from database
	 * only if quizz isn't over and current question isn't answered
	 */
	protected void actionBoutonDroite( ) {
		switch(mode){
		case MODE_NORMAL:
			currentWordId++;
			loadAndDisplayWordFromId(currentWordId);
			restoreTranslationVisibility();
			break;
		case MODE_RANDOM:

			//currentWordId = WordRandomizer.getRandomId(currentWordId, lastWordId);
			if(!QuizzController.getInstance().isFinished()) {
				if(QuizzController.getInstance().isQuestionFinished())
				{
					currentWordId = QuizzController.getInstance().getNextQuestion();
					loadAndDisplayWordFromId(currentWordId);
					restoreTranslationVisibility();
				} else {
					Toast m = Toast.makeText(this, "Il vous reste  : "+QuizzController.getInstance().getNbChancesForQuestion()+" chances ", Toast.LENGTH_SHORT);
					m.show();
				}
			}
			else {
				Toast t = Toast.makeText(this, "Quizz Terminé ", Toast.LENGTH_SHORT);
				t.show();
			}
			((TextView)findViewById(R.id.worddisplaytitle)).setText(getString(R.string.score)+" "+QuizzController.getInstance().getScore());
			break;
		}


	}
	/**
	 * Change the state of {@link WordDisplayer} from quizz to training and other way around
	 */
	protected void changeMode() {
		restoreTranslationVisibility();
		//TODO PREVENIR UTILISATEUR QUE CHANGER DE MODE PERD SES STATS OU LES SAUV EN FONCTION DES PREFERENCES
		mode = (mode == MODE_NORMAL) ? MODE_RANDOM : MODE_NORMAL;
		if(mode == MODE_RANDOM) {
			QuizzController.getInstance().initialise(NB_RANDOM,lastWordId,this);
			currentWordId = QuizzController.getInstance().getNextQuestion();
			loadAndDisplayWordFromId(currentWordId);
			((TextView)findViewById(R.id.worddisplaytitle)).setText(getString(R.string.new_quizz_title));
			findViewById(R.id.bouton_droite_id).setVisibility(View.GONE);
		} else {
			((TextView)findViewById(R.id.worddisplaytitle)).setText(getString(R.string.worddisplay_title));
			findViewById(R.id.bouton_droite_id).setVisibility(View.VISIBLE);
		}
	}

	/**
	 * Change the state of {@link WordDisplayer} to specified state. Restart a quizz if it was alreday the activity state
	 * @param newmode the new state of the activity
	 */
	protected void changeMode(int newMode) {
		restoreTranslationVisibility();
		//TODO PREVENIR UTILISATEUR QUE CHANGER DE MODE PERD SES STATS OU LES SAUV EN FONCTION DES PREFERENCES
		mode = newMode;
		if(mode == MODE_RANDOM) {
			QuizzController.getInstance().initialise(NB_RANDOM,lastWordId,this);
			currentWordId = QuizzController.getInstance().getNextQuestion();
			loadAndDisplayWordFromId(currentWordId);
			((TextView)findViewById(R.id.worddisplaytitle)).setText(getString(R.string.new_quizz_title));
			findViewById(R.id.bouton_droite_id).setVisibility(View.GONE);
		} else {
			((TextView)findViewById(R.id.worddisplaytitle)).setText(getString(R.string.worddisplay_title));
			findViewById(R.id.bouton_droite_id).setVisibility(View.VISIBLE);
		}
	}


	/**
	 * restore display of hidden button related to wrong anwser 
	 * **/
	private void restoreTranslationVisibility() {
		findViewById(R.id.translationDisplay_first).setVisibility(View.VISIBLE);
		findViewById(R.id.translationDisplay_second).setVisibility(View.VISIBLE);
		findViewById(R.id.translationDisplay_third).setVisibility(View.VISIBLE);
		findViewById(R.id.translationDisplay_fourth).setVisibility(View.VISIBLE);
	}

	/***
	 * 
	 * Retrieve dummy translation for {@link currentWordId}
	 * Set 3 of the 4 text view with these dummies
	 * Also change the textview size depending on {@link mainLanguage}
	 * @throws WordNotFoundException
	 */
	protected void fillDummy() throws WordNotFoundException{
		for (int i=0; i<translationsDisplayID.length; i++){
			if(translationsDisplayID[i] != currentRealTranslationDisplayID) {
				Button b = (Button)findViewById(translationsDisplayID[i]);
				b.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
				String mot = "";
				switch(mainLanguage) {
				case MAIN_LANGUAGE_CH:
					mot = WordRandomizer.getRandomFrenchWord(currentWordId, lastWordId,this);
					b.setTextSize(TypedValue.COMPLEX_UNIT_SP, Integer.parseInt(getString(R.string.french_translation_display_size)));
					break;
				case MAIN_LANGUAGE_FR:
					mot = WordRandomizer.getRandomChineseWord(currentWordId, lastWordId, this);
					b.setTextSize(TypedValue.COMPLEX_UNIT_SP, Integer.parseInt(getString(R.string.chinese_translation_display_size)));
					break;
				}


				b.setText(mot);
			}
		}
	}

	/**
	 * GestureDetector used on the {@link TextView} displaying the current word
	 * allows to change word with Fling motion
	 */
	private GestureDetector.SimpleOnGestureListener mScrollHandler = new GestureDetector.SimpleOnGestureListener() {

		private boolean isInBoundOfView(View v,MotionEvent e1) {

			int debutX =(int) e1.getRawX();
			int debutY =(int) e1.getRawY();

			Rect vueRect = new Rect();
			int[] location = new int[2];

			v.getDrawingRect(vueRect);
			v.getLocationOnScreen(location);

			vueRect.offsetTo(location[0], location[1]);


			if (vueRect.contains(debutX,debutY )) {
				return true;
			}
			return false;
		}

		public boolean onFling(MotionEvent e1, MotionEvent e2,
				float velocityX, float distanceY) {

			if (Math.abs(velocityX) > minVelocity) {

				if (isInBoundOfView(WordDisplayer.this.findViewById(R.id.layoutmotid), e1)
						&&
						isInBoundOfView(WordDisplayer.this.findViewById(R.id.layoutmotid), e2)) {

					//Log.d("msg","ON COMMENCE LE TEST : "+distanceX);

					if (velocityX <= minVelocity){
						actionBoutonDroite();
						return true;
					}
				}
			}
			return false;
		}

	};

	/** 
	 * Send {@link MotionEvent} to gesture detector
	 * @param event the {@link MotionEvent}
	 */
	public boolean onTouchEvent(MotionEvent event) {
		return mGestureDetector.onTouchEvent(event);
	}


	/**
	 * {@link Activity} method used to create {@link ContextMenu}
	 */
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		// TODO Auto-generated method stub
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.setHeaderIcon(R.drawable.icon);

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.worddisplaymenu, menu);
	}

	/** Gestion du Menu **/

	/**
	 * Handles callback from Menu selection
	 * @param item the {@link MenuItem} that was selected
	 */
	public boolean onContextItemSelected(MenuItem item) {

		Intent intent;
		
		switch(item.getItemId()){

		case R.id.menu_dico:
			intent = new Intent(this,Dictionary.class);
			startActivity(intent);
			break;
		case R.id.entrainement_mode:
			changeMode(MODE_NORMAL);
			break;
		case R.id.quizz_mode:
			changeMode(MODE_RANDOM);
			break;
		case R.id.switch_lg:
			mainLanguage = (mainLanguage == MAIN_LANGUAGE_CH ) ? MAIN_LANGUAGE_FR : MAIN_LANGUAGE_CH;
			displayCurrentWord();
			break;

		case R.id.settings: 
			intent = new Intent(this,Settings.class);
			startActivityForResult(intent,REQUEST_PREFERENCE);
			break;
		
		case R.id.to_score_view:
			intent =  new Intent(this,StatDisplayer.class);
			startActivity(intent);
			break;
		}

		return super.onContextItemSelected(item);
	}

	/** Gestion des clics sur les traductions **/
	
	/** {@link TranslationListener} for this {@link Activity}**/
	private TranslationListener translationListener = new TranslationListener();
	
	/**
	 * 
	 * This class handles click on each of the 4 {@link TextView} displaying translation for the current
	 * word. Use a {@link QuizzController} to know if the translation clicked was the good one.
	 */
	private class TranslationListener implements OnClickListener {

		public TranslationListener(){}

		public void onClick(View v) {

			if(v.getId() == currentRealTranslationDisplayID) {

				switch(mode){

				case MODE_RANDOM:
				{
					if(!QuizzController.getInstance().isQuestionFinished()){
						QuizzController.getInstance().goodAnswer();
						((Button)v).setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ok, 0);

						v.setAnimation(AnimationUtils.loadAnimation(WordDisplayer.this, R.anim.agitation));
						v.getAnimation().setAnimationListener(WordDisplayer.this.setAnimationView(v));
						v.startAnimation(v.getAnimation());
					}else{
						actionBoutonDroite();
					}
				}
				break;


				default:
					((Button)v).setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ok, 0);
					break;
				}

			}else {


				switch(mode){

				case MODE_RANDOM: 
				{
					if(!QuizzController.getInstance().isQuestionFinished()){
						QuizzController.getInstance().badAnswer();
						((Button)v).setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ko, 0);
						v.setAnimation(AnimationUtils.loadAnimation(WordDisplayer.this, R.anim.slide_droite));
						v.getAnimation().setAnimationListener(WordDisplayer.this.setAnimationView(v));
						v.startAnimation(v.getAnimation());
					} else {
						actionBoutonDroite();
					}
				}	

				break;

				default:
					((Button)v).setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ko, 0);
					break;
				}
			}
		}

	}


	/** Retour de l'animation **/
	public void onAnimationEnd(Animation animation) {
		animatedAnwser.setVisibility(View.GONE);
		if (QuizzController.getInstance().getCurrentAnswer() == Question.FAIL || QuizzController.getInstance().getCurrentAnswer() == Question.SUCCESS) {
			actionBoutonDroite();
		}
	}

	public void onAnimationRepeat(Animation animation) {

	}

	public void onAnimationStart(Animation animation) {

	}

	public WordDisplayer setAnimationView(View v){
		animatedAnwser = v;
		return this;
	}

	/** Load preference from sharedprefrence */
	private void loadPreferences(){
		SharedPreferences pref  = PreferenceManager.getDefaultSharedPreferences(this);
		NB_RANDOM =Integer.parseInt(pref.getString("list_difficulte", "20"));
	}

	@Override
	protected void onStop() {
		//GoogleAnalyticsTracker.getInstance().dispatch();
		super.onStop();
	}
	
	@Override
	protected void onDestroy() {
		//GoogleAnalyticsTracker.getInstance().stop();
		super.onDestroy();
	}
	
}

